#include <iostream>
using namespace std;
#include <string.h>

namespace ljx
{
  class string
  {
    public:
      string(const char* str = "")
        :_str(new char[strlen(str)+1])
      {
          strcpy(_str,str);
      }

      //传统写法
      //拷贝构造
      //s2(s1)
      //string(const string& s)
      //  :_str(new char[strlen(s._str)+1])
      //{
      //    strcpy(_str,s._str);
      //}
      
      //现代写法
      
      //s2(s1)
      string(const string& s)
      :_str(nullptr)//这里不置空，析构的时候会崩溃
      {
        string tmp(s._str);//复用构造函数
        swap(_str,tmp._str);
      }


      //传统写法
      //赋值拷贝重载
      //s2 =s1
      //string& operator=(const string& s)
      //{
      //    if(this!=&s)
      //    {
      //      char* tmp = new char[strlen(s._str)+1];
      //      strcpy(tmp,s._str);
      //      delete[] _str;
      //      _str = tmp;
      //    }
      //    return *this;
      //}
      
      //现代写法
      //s2=s1
      //string& operator=(const string& s)
      //{
      //  if(this!=&s)
      //  {
      //    string tmp(s);//复用拷贝构造，也可以复用构造函数   string tmp(s._str)
      //    swap(_str,tmp._str);//tmp是局部的对象，出了作用域会自动销毁，不用我们释放空间
      //  }
      //  return *this;
      //}
      //现代写法2(本质是一样的，更简洁一点)
      string& operator=(string s)
      {
        //这里不用考虑自己给自己赋值的问题了，因为传参是拷贝构造，地址不一样了
        swap(_str,s._str);
        return *this;
      }

      ~string()
      {
        delete[] _str;
        _str = nullptr;
      }
    private:
    char* _str;
  };

  void test1()
  {
    string s1("hello");
    string s2;
    string s3(s1);
    s2 =s3;
  }
}





int main()
{

  ljx::test1();
  return 0;
}
